package com.vvv.myapiclientsdk.client;

import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.vvv.myapiclientsdk.model.request.AbstractRequest;
import com.vvv.myapiclientsdk.model.request.TestRequest;
import com.vvv.myapiclientsdk.model.response.AbstractResponse;
import com.vvv.myapiclientsdk.model.response.CustomizedResponse;
import com.vvv.myapiclientsdk.model.response.TestResponse;
import com.vvv.myapiclientsdk.utils.SignUtils;
import org.apache.commons.lang3.StringUtils;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
 * @author vvv
 * @date 2023-12-05 15 58
 * discription
 */
public abstract class AbstractClient {
    // api签名验证
    private String accessKey;
    private String secreteKey;

    // api签名验证
    public static final String GATEWAY_HOST = "http://localhost:8090";

    public AbstractClient(String accessKey, String secreteKey) {
        this.accessKey = accessKey;
        this.secreteKey = secreteKey;
    }

    /**
     * 测试接口
     * @param testRequest
     * @return
     */
    public boolean interfaceIsOk(TestRequest testRequest) {
        int code = this.doRequest(testRequest, TestResponse.class).getCode();
        return code >= 200 && code < 300;
    }

    /**
     * 发送请求
     * @param request
     * @param clazz
     * @return
     * @param <T>
     */
    public <T extends AbstractResponse> T doRequest(AbstractRequest request, Class<T> clazz) {
        String urlStr = request.getUrl();
        Long interfaceId = request.getId();
        String method = request.getMethod();
        // 检查参数
        if (StringUtils.isAnyEmpty(urlStr, method) || interfaceId == null) {
            throw new UnsupportedOperationException("url or interfaceId or method can not be empty");
        }
        if (!method.equals("GET") && !method.equals("POST")) {
            throw new UnsupportedOperationException("request method error !");
        }
        // 构建请求
        HttpRequest httpRequest;
        String requestBody = JSONUtil.toJsonStr(request);
        // url to path
        String path = "";
        try {
            URL url = new URL(urlStr);
            path = url.getPath();
        } catch (MalformedURLException e) {
            throw new RuntimeException("url error");
        }
        if (method.equals("GET")) {
            httpRequest = HttpRequest.get(GATEWAY_HOST + path);
        } else {
            httpRequest = HttpRequest.post(GATEWAY_HOST + path);
        }
        // send request
        HttpResponse response = httpRequest.addHeaders(this.getHeaderMap(requestBody))
                .body(requestBody)
                .execute();
        String body = response.body();
        try {
            T result;
            // 判断是不是自定义的请求
            if (clazz == CustomizedResponse.class) {
                result = clazz.newInstance();
                result.setCustomizedParams(JSONUtil.toBean(body,
                        new TypeReference<Map<String, Object>>() {}, false));
            } else {
                result = JSONUtil.toBean(body, clazz);
            }
            result.setCode(response.getStatus());
            return result;
        } catch (Exception e) {
            throw new RuntimeException("sdk error" + e);
        }
    }

    /**
     * 签名
     * @param body
     * @return
     */
    private Map<String, String> getHeaderMap(String body) {
        Map<String, String> map = new HashMap<>();
        // 在请求头中加入以下参数
        // 1. ak
        map.put("accessKey", accessKey);
        // 2. 时间搓 防止重放
        map.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
        // 3. nonce 随机数 防止重放
        map.put("nonce", RandomUtil.randomNumbers(4));
        // 4. sign 签名，
        map.put("sign", SignUtils.getSign(body, this.secreteKey));
        // 5. 用户参数
        map.put("body", body);
        return map;
    }
}
